#include "iic.h"
#include "delay.h"
#include "stm32f0xx.h"
#define SlaveAddress  0x32   //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
                              //ALT  ADDRESS引脚接地时地址为0x30，接电源时地址为0x32
void IIC_Init(void)  
{            
   GPIO_InitTypeDef GPIO_InitStructure;  
   RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOB, ENABLE ); //使能B口时钟  
      
   GPIO_InitStructure.GPIO_Pin = PIN_SCL | PIN_SDA;  
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ;       //推挽输出  
	 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(I2C_PORT, &GPIO_InitStructure); 
	 GPIO_SetBits(I2C_PORT,PIN_SDA);  //SDA =1  
	 GPIO_SetBits(I2C_PORT,PIN_SCL);  //SCL=1  
}  
//产生I2C开始信号  
void LIS3DH_Start(void)  
{  
   SDA2_OUT();                    //sda线输出  
   GPIO_SetBits(I2C_PORT,PIN_SDA);  //SDA =1  
   delay_us(10);  
   GPIO_SetBits(I2C_PORT,PIN_SCL);  //SCL=1  
   delay_us(10);  
   GPIO_ResetBits(I2C_PORT,PIN_SDA);//SDA=0  
   delay_us(10);  
   GPIO_ResetBits(I2C_PORT,PIN_SCL);//SCL=0  
}    
   
//产生I2C停止信号  
void LIS3DH_Stop(void)  
{  
   SDA2_OUT();  //sda线输出  
   GPIO_ResetBits(I2C_PORT,PIN_SDA);     
   delay_us(10);  
   GPIO_SetBits(I2C_PORT,PIN_SCL);   
   delay_us(10);  
   GPIO_SetBits(I2C_PORT,PIN_SDA);   
   delay_us(10);  
   GPIO_ResetBits(I2C_PORT, PIN_SCL);//SCL=0;   
   delay_us(10);            
}  
//等待应答信号到来  
//返回值：1，接收应答失败  
//        0，接收应答成功  
u8 I2C_Wait_Ack(void)  
{  
   u8 ucErrTime=0;  
   SDA2_IN();      //SDA设置为输入    
   GPIO_SetBits(I2C_PORT,PIN_SDA);  
   delay_us(5);      
   GPIO_SetBits(I2C_PORT,PIN_SCL);   
   delay_us(5);    
   while(GPIO_ReadInputDataBit(I2C_PORT,PIN_SDA))  
   {  
      ucErrTime++;  
      if(ucErrTime>250)  
      {  
         LIS3DH_Stop();     
         return 1;  
      }  
   }  
   GPIO_ResetBits(I2C_PORT, PIN_SCL);      
   return 0;    
}  
  
//产生ACK应答  
void I2C_Ack(void)  
{  
   GPIO_ResetBits(I2C_PORT,PIN_SCL);  
   SDA2_OUT();  
   GPIO_ResetBits(I2C_PORT,PIN_SDA);  
   delay_us(5);  
   GPIO_SetBits(I2C_PORT,PIN_SCL);  
   delay_us(5);  
   GPIO_ResetBits(I2C_PORT,PIN_SCL);  
}  
  
//不产生ACK应答        
void I2C_NAck(void)  
{  
   GPIO_ResetBits(I2C_PORT,PIN_SCL);  
   SDA2_OUT();  
   GPIO_SetBits(I2C_PORT,PIN_SDA);  
   delay_us(5);  
   GPIO_SetBits(I2C_PORT,PIN_SCL);   
   delay_us(5);  
   GPIO_ResetBits(I2C_PORT,PIN_SCL);  
}    
               
//I2C发送一个字节  
//返回从机有无应答  
//1，有应答  
//0，无应答       
void LIS3DH_SendByte(u8 txd)  
{                          
    u8 t;     
    SDA2_OUT();        
    GPIO_ResetBits(I2C_PORT,PIN_SCL);//拉低时钟开始数据传输  
    for(t=0;t<8;t++)  
    {                
        if((txd&0x80)==0x80)     
          {GPIO_SetBits(I2C_PORT, PIN_SDA);}//SDA=1，写 1                  
        else    
          {GPIO_ResetBits(I2C_PORT, PIN_SDA);}//SDA=0，写 0   
        txd<<=1;      
       delay_us(5);   //对TEA5767这三个延时都是必须的    
       GPIO_SetBits(I2C_PORT,PIN_SCL);   
       delay_us(5);   
       GPIO_ResetBits(I2C_PORT,PIN_SCL);  
       delay_us(5);  
    }    
}       
  
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK     
u8 LIS3DH_RecvByte(unsigned char ack)  
{  
    unsigned char i,receive=0;  
    SDA2_IN();//SDA设置为输入  
    for(i=0;i<8;i++ )  
 {  
        GPIO_ResetBits(I2C_PORT,PIN_SCL);  
        delay_us(5);  
        GPIO_SetBits(I2C_PORT,PIN_SCL);  
        receive<<=1;  
        if(GPIO_ReadInputDataBit(I2C_PORT,PIN_SDA))receive++;     
        delay_us(5);   
    }        
    if (!ack)  
        I2C_NAck();//发送nACK  
    else  
        I2C_Ack(); //发送ACK     
    return receive;  
}  
void SDA2_IN(void)  
{  
   GPIO_InitTypeDef GPIO_InitStruct;  
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;    //上拉输入 
	 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
   GPIO_InitStruct.GPIO_Pin = PIN_SDA;  
   GPIO_Init(I2C_PORT, &GPIO_InitStruct );  
}  
void SDA2_OUT(void)  
{  
   GPIO_InitTypeDef GPIO_InitStruct;  
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;   
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
	 GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
   GPIO_InitStruct.GPIO_Pin = PIN_SDA;  
   GPIO_Init(I2C_PORT, &GPIO_InitStruct );  
}  
//******单字节写入*******************************************
 
void Single_Write_LIS3DH(u8 REG_Address,u8 REG_data)
{
    LIS3DH_Start();                  //起始信号
    LIS3DH_SendByte(SlaveAddress);   //发送设备地址+写信号
	  I2C_Wait_Ack();       
    LIS3DH_SendByte(REG_Address);    //内部寄存器地址，请参考中文pdf22页 
		I2C_Wait_Ack();       
    LIS3DH_SendByte(REG_data);       //内部寄存器数据，请参考中文pdf22页 
	  I2C_Wait_Ack(); 
    LIS3DH_Stop();                   //发送停止信号
}
//********单字节读取*****************************************
u8 Single_Read_LIS3DH(u8 REG_Address)
{  
		u8 REG_data;
    LIS3DH_Start();                          //起始信号
    LIS3DH_SendByte(SlaveAddress);           //发送设备地址+写信号
		REG_data=I2C_Wait_Ack(); 
    LIS3DH_SendByte(REG_Address);            //发送存储单元地址，从0开始 
		REG_data=I2C_Wait_Ack(); 
    LIS3DH_Start();                          //起始信号
    LIS3DH_SendByte(SlaveAddress+1);         //发送设备地址+读信号
	  REG_data=I2C_Wait_Ack(); 
    REG_data=LIS3DH_RecvByte(0);              //读出寄存器数据
    LIS3DH_Stop();                           //停止信号
    return REG_data; 
}

